import 'reflect-metadata'

/**
 * http 请求方法相关的装饰器\
 * 工厂 返回一个 Get 请求路由处理函数
 */
export function Get(path: string = '') {
  /**
   * 方法装饰器装饰在类的原型的方法上\
   * 类的原型对象 被装饰的方法名 属性描述符
   */
  return (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
    // 给类的原型上的方法添加一个 path 元数据 值是 path
    Reflect.defineMetadata('path', path, descriptor.value)
    // 给类的原型上的方法添加一个 method 元数据 值是 'GET'
    Reflect.defineMetadata('method', 'GET', descriptor.value)
  }
}


/**
 * http 请求方法相关的装饰器\
 * 工厂 返回一个 Post 请求路由处理函数
 */
export function Post(path: string = '') {
  /**
   * 方法装饰器装饰在类的原型的方法上\
   * 类的原型对象 被装饰的方法名 属性描述符
   */
  return (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
    // 给类的原型上的方法添加一个 path 元数据 值是 path
    Reflect.defineMetadata('path', path, descriptor.value)
    // 给类的原型上的方法添加一个 method 元数据 值是 'POST'
    Reflect.defineMetadata('method', 'POST', descriptor.value)
  }
}


/**
 * http 请求方法相关的装饰器\
 * 工厂 返回一个 Post 请求路由处理函数
 * statusCode 默认值 302 代表临时重定向
 *   301 代表永久重定向
 */
export function Redirect(url: string = '', statusCode: number = 302) {
  /**
   * 方法装饰器装饰在类的原型的方法上\
   * 类的原型对象 被装饰的方法名 属性描述符
   */
  return (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
    Reflect.defineMetadata('redirectUrl', url, descriptor.value)
    Reflect.defineMetadata('redirectStatusCode', statusCode, descriptor.value)
  }
}


/**
 * http 请求方法相关的装饰器\
 * 工厂 返回一个 HttpCode 装饰器 用于设置响应状态码
 */
export function HttpCode(statusCode: number = 200) {
  /**
   * 方法装饰器装饰在类的原型的方法上\
   * 类的原型对象 被装饰的方法名 属性描述符
   */
  return (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
    Reflect.defineMetadata('statusCode', statusCode, descriptor.value)
  }
}

/**
 * http 请求方法相关的装饰器\
 * 工厂 返回一个 Header 装饰器 指定自定义响应头
 */
export function Header(name: string, value: string) {
  /**
   * 方法装饰器装饰在类的原型的方法上\
   * 类的原型对象 被装饰的方法名 属性描述符
   */
  return (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
    // 取出 headers 响应头数组 默认值为空数组
    const existingHeaders = Reflect.getMetadata('headers', descriptor.value) || []
    existingHeaders.push({ name, value })
    // 保存响应头数组
    Reflect.defineMetadata('headers', existingHeaders, descriptor.value)
  }
}
